home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Programmer Power Tools
/
Programmer Power Tools.iso
/
packet
/
cbbs60so.arc
/
MBMAIL.C
< prev
next >
Wrap
Text File
|
1989-02-17
|
40KB
|
1,780 lines
/*
* MBMAIL.C - 2/04/89 The message file stuff, except for forwarding.
*/
#include "mb.h"
#define btmax 112 /* Max text in beacon line */
char orgmsg[6], orgbbs[7], orgtime[5], orgdate[7];
char *mbfile, *mbbfile, *msgdir, *bidfile;
char *ufwd; /* Calls with unread msgs, for BT */
char *bfwd; /* Calls with unread msgs, for forwarding */
short ufwdm, ufwdn, bfwdm, bfwdn;
short tstaleb, tstalen, tstaleu;
int bidok, hidok, hasbid, needbid, holdit;
char *mm[num_mm];
char wpcall[ln_call];
XBBS *xbbs;
HOLD *hold;
MAIL_HDR *mfhs;
MSG_HDR *tmmhs;
FILE *bfl;
int mfl, mflb;
msgfile(p, n)
char *p;
word n;
{
sprintf(p, "%s%u", msgdir, n);
}
/*
* Open file to hold BIDs
*/
opnbid()
{
if ((bfl = fopen(bidfile, "a+")) is NULL) { nofile(bidfile); exit(1); }
fclose(bfl);
}
/*
* Write message header.
*/
wt_mmhs()
{
if (port->mmhs->rn) write_rec (mfl, port->mmhs->rn, (char *)port->mmhs);
}
/*
* Get message title.
*/
get_title()
{
while(!getdat());
remnl(port->line);
strncpy(port->mmhs->title, port->line, mhtitl);
}
/*
* Parse the [@ bbs] and [< from] fields of a command.
*/
atfrom(i)
int i;
{
if (*port->fld[i] is '<') pcall(port->mmhs->from, port->fld[i + 1]);
else if (*port->fld[i] is '@')
{
pcall(port->mmhs->bbs, port->fld[i +1]);
if ((strchr(port->fld[i + 1], '.')) is NULL) return;
port->mmhs->ext = 2;
fill (port->mmhs->call, '\0', 125);
strncpy(port->mmhs->call[0], port->fld[i + 1], 64);
}
}
/*
* Parse the fields of a send command.
*/
pfld()
{
hasbid = false;
port->mmhs->type = port->opt2;
pcall(port->mmhs->to, port->fld[1]);
strncpy(port->mmhs->from, port->user->call, ln_call);
fill(port->mmhs->bbs, ' ', ln_call);
fill(port->mmhs->bid, ' ', ln_bid);
port->mmhs->ext = 0;
if (port->flds > 3) atfrom(port->flds - 2);
if (port->flds > 5) atfrom(port->flds - 4);
if (port->flds > 2)
if(*port->fld[port->flds-1] is '$')
{
if (*(port->fld[port->flds - 1] + 1) isnt NULL)
{
strncpy(port->mmhs->bid, port->fld[port->flds - 1] + 1, ln_bid);
hasbid = true;
}
if (port->flds > 4) atfrom(port->flds - 3);
if (port->flds > 6) atfrom(port->flds - 5);
}
initmsg(true);
if(!bidok) {
if (port->user->options & (u_bbs | u_expert)) outstr("Sj:\n");
else prtx(mm[0]);
get_title();
return;
}
else {
if (hasbid) {
checkbid();
if (!needbid) {
outstr("No - Already have it\n");
sprintf(port->mmhs->title, "<<%6.6s - %s>>",
port->user->call, port->fld[port->flds-1]);
wt_mmhs();
return;
}
prtx("OK $C\n");
get_title();
return;
}
else {
prtx("OK $C\n");
get_title();
needbid = true; /* will check and may assign one later */
return;
}
}
}
/*
* Create the header line.
*/
makehdr()
{
register char st;
st = 'N';
if (port->mmhs->stat & m_stale) st = 'O';
if (port->mmhs->stat & m_fwd) st = 'F';
if (port->mmhs->stat & m_read) st = 'Y';
if (port->mmhs->stat & m_hold) st = 'H';
if (port->mmhs->stat & m_kill) st = 'K';
if (port->mmhs->stat & m_busy) st = 'B';
sprintf(tmp->scr,"%5u %c%c %5u %6.6s %6.6s %6.6s %4.4s/%4.4s %s\n",
port->mmhs->number, port->mmhs->type, st, port->mmhs->size,
port->mmhs->to, port->mmhs->from, port->mmhs->bbs,
port->mmhs->date + 2, port->mmhs->time, port->mmhs->title);
}
/*
* Write mail.dat header into text file
*/
makehdr2()
{
register char st, c;
int msfl;
char flags[mmesn];
fill (flags, ' ',mmesn);
fill (tmp->scr, '\0', 256);
tmp->scr[254] = '\r'; tmp->scr[255] = '\n';
if (port->mmhs->ext is 1)
{
for (c=0; c < port->mmhs->count; c++)
flags[c] = port->mmhs->flag[c] + '0';
}
st = 'N';
if (port->mmhs->stat & m_stale) st = 'O';
if (port->mmhs->stat & m_fwd) st = 'F';
if (port->mmhs->stat & m_hold) st = 'H';
if (port->mmhs->stat & m_read) st = 'Y';
if (port->mmhs->stat & m_kill) st = 'K';
sprintf(tmp->scr,
"%5u %c%c %5u %6.6s %6.6s %6.6s %6.6s %4.4s %-12.12s %5u\r\n",
port->mmhs->number, port->mmhs->type, st, port->mmhs->size,
port->mmhs->to, port->mmhs->from, port->mmhs->bbs,
port->mmhs->date, port->mmhs->time, port->mmhs->bid, port->mmhs->read);
if (port->mmhs->ext is 2)
sprintf(tmp->scr+68, "%c %s\r\n%s\r\n", port->mmhs->ext +'0',
port->mmhs->call, port->mmhs->title);
else sprintf(tmp->scr+68, "%c %16.16s\r\n%s\r\n", port->mmhs->ext +'0',
flags, port->mmhs->title);
msgfile(port->cmd, port->mmhs->number);
if ((msfl = open(port->cmd, O_WRONLY | O_BINARY)) < 0) return;
write_rec(msfl, 0, (char *)tmp->scr);
close(msfl);
}
/*
* Print a message header.
*/
prthdr(tit)
int tit;
{
char *a, *b;
register short i;
register short docc;
if (tit) prtx(mm[3]);
makehdr();
outstr(tmp->scr);
if((port->opt1 is'L')and((*port->fld[1]isnt';')and(*port->fld[2]isnt';')))
return;
if (port->mmhs->ext is 2)
{
outstr(" EF:");
outstr(port->mmhs->call);
outchar('\n');
}
if (port->mmhs->ext is 1) if (port->mode & ops)
{
docc = false;
for (i = 0; i < port->mmhs->count; i++) if (port->mmhs->flag[i])
docc = true;
if (docc)
{
outstr(" cc:");
for (i = 0; i < port->mmhs->count; i++)
{
if (port->mmhs->flag[i]) outchar(' '); else outstr(" *");
outnb(port->mmhs->call[i], ln_call);
}
outchar('\n');
}
}
if (port->mode & ops) if (*port->mmhs->bid isnt ' ')
{
outstr(" BID: ");
a = port->line;
b = port->mmhs->bid;
unbl(a, b, ln_bid);
outstr(port->line); outchar('\n');
}
}
/*
* Read the message, look for the last bbs header.
* Set the @ field of the current message to the "at bbs" in that header.
*/
findat()
{
register short i;
fill(port->mmhs->bbs, ' ', ln_call);
msgfile(port->line, port->mmhs->number);
if ((port->fl = fopen(port->line, "r")) is NULL) { nofile(port->line); return; }
fseek(port->fl, (long)RECSIZE, 0);
while(fgets(port->line, linelen, port->fl) isnt NULL)
{
if (!parsehd(port->line)) break;
pcall(port->mmhs->bbs, orgbbs);
}
fclose (port->fl);
}
/*
* Parse a message header line.
*/
parsehd(in)
char *in;
{
register char *p;
register int count, n;
if (!ishead(in)) return false;
if ((p = strchr(in, 'R')) is NULL) return false;
{
p++;
if (*p is ':') p++;
if (*p is ' ') p++;
count = 6;
n = 0;
while (*p and count--)
{
if (!isalnum(*p)) break;
orgdate[n++] = *p++;
}
orgdate[n] = '\0';
if (*p is '/') p++;
count = 4;
n = 0;
while (*p and count--)
{
if (!isalnum(*p)) break;
orgtime[n++] = *p++;
}
orgtime[n] = '\0';
}
if ((p = strchr(in, '@')) is NULL) return false;
{
p++;
/* skip colon or a space in @:call OR @ call */
if (*p is ':') p++;
if (*p is ' ') p++;
count = ln_call;
n = 0;
while (*p and count--)
{
if (!isalnum(*p)) break;
toupper(*p);
orgbbs[n++] = *p++;
}
orgbbs[n] = '\0';
}
if ((p = strchr(in, '#')) isnt NULL)
{
p++;
if (*p is ':') p++;
if (*p is ' ') p++;
count = 5;
n = 0;
while (*p and count--)
{
if (!isalnum(*p)) break;
orgmsg[n++] = *p++;
}
orgmsg[n] = '\0';
}
else
{
p = strchr(in, '@');
p--; count = 5;
while(count-- and *p isnt ' ') p--;
p++;
if (*p is '<') p++;
count = 5;
n = 0;
while (*p and count--)
{
if (*p is '@') break;
orgmsg[n++] = *p++;
}
orgmsg[n] = '\0';
}
return true;
}
/*
* Find a message given it's number.
*/
findmsg(nr)
word nr;
{
register word i;
for (i = mfhs->last; i; i--)
{
read_rec(mfl, i, (char *)port->mmhs);
if (port->mmhs->number is nr) return true;
if (port->mmhs->number < nr) return false;
}
return false;
}
/*
* Create the distribution list, if required.
*/
dodis()
{
register FILE *dfl;
if (port->mmhs->ext is 2) return;
port->mmhs->ext = 0;
if (*port->mmhs->bbs is ' ') return;
unbl(tmp->scr, port->mmhs->bbs, ln_call);
strcpy(port->line, msgdir);
strcat(port->line, tmp->scr);
strcat(port->line, ".DIS");
if ((dfl = fopen(port->line, "r")) is NULL) return;
port->mmhs->ext = 1 ;
for (port->mmhs->count = 0;
(port->mmhs->count < mmesn) and (fgets(tmp->scr, scrmax, dfl) isnt NULL);
port->mmhs->count++)
{
strupr(tmp->scr);
pcall(port->mmhs->call[port->mmhs->count], tmp->scr);
if(matchn(port->mmhs->call[port->mmhs->count], port->user->call, ln_call))
port->mmhs->flag[port->mmhs->count] = false;
else port->mmhs->flag[port->mmhs->count] = true;
}
fclose(dfl);
}
/*
* Do we hold this message?
*/
ishold(c)
char *c;
{
register HOLD *hp;
for (hp = hold; hp isnt NULL; hp = hp->next)
if (matchn(hp->call, c, ln_call)) return true;
return false;
}
/*
* Create message utilities - initmsg and cremsg.
* Used by "send message", "make message from file",
* "kill msg" (service messages), "copy message".
*/
initmsg(h)
int h;
{
if (s_flag & s_dv) begin_lock();
read_rec(mfl, 0, (char *)mfhs);
port->mmhs->rn = mfhs->next++;
port->mmhs->number = mfhs->next_msg++;
port->mmhs->stat = m_busy;
strncpy(port->mmhs->date, l_date, ln_date);
strncpy(port->mmhs->time, l_time, ln_time);
port->mmhs->read = 0;
port->mmhs->size = 0;
if(port->mmhs->ext isnt 2) fill(port->mmhs->call, '\0', 125);
if(h)sprintf(port->mmhs->title, "<<%6.6s -- disconnected>>",port->user->call);
/*
* Clean up the file header.
*/
if (!mfhs->first) mfhs->first = port->mmhs->rn;
mfhs->last = port->mmhs->rn;
mfhs->count++;
write_rec(mfl, 0, (char *)mfhs);
wt_mmhs();
mfhs->next_msg--;
if (s_flag & s_dv) end_lock();
}
cremsg()
{
char *a, *b;
register short i;
register XBBS *xp;
register FILE *out;
port->mmhs->stat = 0;
strncpy(port->mmhs->date, l_date, ln_date);
strncpy(port->mmhs->time, l_time, ln_time);
port->mmhs->read = 0;
port->mmhs->size = filesize;
for (xp = xbbs; xp isnt NULL; xp = xp->next)
if (wcm(xp->from, port->mmhs->bbs))
{
strncpy(port->mmhs->bbs, xp->to, ln_call);
break;
}
if (ishold(port->mmhs->to)) port->mmhs->stat = m_hold;
if (ishold(port->mmhs->from)) port->mmhs->stat = m_hold;
if (ishold(port->mmhs->bbs)) port->mmhs->stat = m_hold;
if (holdit) port->mmhs->stat = m_hold;
if (*port->mmhs->bid isnt ' ') {
checkbid();
if (hasbid) if (!holdit) if (needbid) {
if ((out = fopen(bidfile,"a")) is NULL) {
port->msg = mcant; return;
}
a = port->cmd;
b = port->mmhs->bid;
unbl(a, b, ln_bid);
sprintf(port->line, "%4.4s%s\n", port->mmhs->date + 2, port->cmd);
if (s_flag & s_dv) begin_lock();
fputs(port->line, out);
if (s_flag & s_dv) end_lock();
fclose(out);
}
}
dodis();
if ((port->mmhs->ext is 1) and (*port->mmhs->bid is ' '))
port->mmhs->stat = m_hold;
wt_mmhs();
makehdr2();
if (*port->fld[port->flds-1] isnt '$') port->fld[port->flds-1] = nullstr;
sprintf(port->line, "%u %-.6s@%-.6s %s %s", port->mmhs->number,
port->mmhs->to, port->mmhs->bbs, port->fld[port->flds-1], port->mmhs->title);
log('M', port->opt1, port->opt2, port->line);
mfhs->next_msg++;
}
/*
* Set up the beacon line.
*/
setfwd()
{
register char *cp, *lp;
register short i;
bldfwd();
if (ufwdm > 1)
{
strcpy(port->line, "BT Mail for:");
cp = ufwd;
lp = port->line + strlen(port->line);
while ((cp < ufwd + ln_call * ufwdn) and (lp < port->line + btmax))
{
*lp++ = ' ';
for (i = 0; i < ln_call; i++, cp++) if (*cp isnt ' ') *lp++ = *cp;
}
*lp++ = '\n';
*lp = '\0';
alltnc(port->line);
}
}
/*
* General permission check: sysop or TO or FROM.
*/
permit()
{
if (port->mmhs->stat & (m_kill | m_busy)) return false;
if (matchn(port->user->call, port->mmhs->to, ln_call)) return true;
if (matchn(port->user->call, port->mmhs->from, ln_call)) return true;
return false;
}
/*
* Return true if user has kill permission for current message.
*/
kpermit()
{
if (port->mmhs->stat & m_kill) return false;
if (port->mode & ops) return true;
if (permit()) return true;
return ((port->mmhs->type is 'T') and (port->opt2 is 'T'));
}
/*
* Return true if user has list permission for current message.
*/
lpermit()
{
if (port->user->options & u_sysop) return true;
if (permit()) return true;
return ((port->mmhs->type isnt 'P')
and !(port->mmhs->stat & (m_fwd | m_kill | m_busy)));
}
/*
* Return true if user has read permission for current message.
*/
rpermit()
{
if ( port->mode & ops) return true;
if (permit()) return true;
return (port->mmhs->type isnt 'P');
}
/*
* Clean the mail file.
* Force drain of buffers, update of directory item.
*/
clnmsg()
{
close(mfl);
mfl = open(mbfile, O_RDWR | O_BINARY);
}
/*
* Close the mail file.
*/
clsmsg()
{
close (mfl);
}
/*
* Open the mail file.
*/
opnmsg()
{
register char *tp;
/*
* Allocate space for the mail file records.
*/
mfhs = (MAIL_HDR *) malloc(sizeof(MAIL_HDR));
tmmhs = (MSG_HDR *) malloc(sizeof(MSG_HDR));
/*
* Allocate the "who has mail" lists.
*/
ufwd = (char *) malloc (ln_call * ufwdm);
bfwd = (char *) malloc (ln_call * bfwdm);
if (bfwd is NULL) errall();
/*
* Open the file. If it does not exist, make one.
*/
if ((mfl = open(mbfile, O_RDWR | O_BINARY)) < 0)
{
if ((mfl = open(mbfile, O_CREAT | O_RDWR | O_BINARY, pmode)) < 0)
{ nofile(mbfile); exit(1); }
inithdr();
mfhs->next_msg = 1;
write_rec(mfl, 0, (char *)mfhs);
}
/*
* Read the mail file header.
*/
read_rec(mfl, 0, (char *)mfhs);
/*
* If wrong version mail file, quit now.
*/
if (mfhs->version isnt mb_version)
{
printf("Expected version %d, got version %d\n",
mb_version, mfhs->version);
nofile(mbfile);
exit(1);
}
}
/*
* Initialize the mail file header.
*/
inithdr()
{
mfhs->next = 1;
mfhs->first = 0;
mfhs->last = 0;
mfhs->version = mb_version;
mfhs->free = 0;
mfhs->count = 0;
mfhs->unt_msg = 1;
curtim();
strncpy(mfhs->date, l_date, ln_date);
strncpy(mfhs->time, l_time, ln_time);
fill(mfhs->unu, '\0', mfhsunu);
}
/*
* Open mail file and read first record.
*/
readmsg()
{
mfl = open(mbfile, O_RDWR | O_BINARY);
read_rec(mfl, 0, (char *)mfhs);
}
/*
* Does this station want us to send BIDs ?
*/
isbid()
{
register char *f;
/* Is this a sid? It must have a '-' and end with a ']' */
if ((port->line[strlen(port->line) - 2] isnt ']' ) or
((f = strrchr(port->line, '-')) is NULL))
return;
/* Look for specal characters in the last field. */
f++;
for (; *f isnt ']';f++)
switch(*f)
{
case 'H' : hidok = true; break;
case '$' : if(*(f+1) is ']') bidok = true; break;
}
}
/*
* Check to see whether we already have this BID.
*/
checkbid()
{
FILE *out;
char *a, *b;
if (*port->mmhs->bid is ' ') { needbid = true; return; }
if ((out = fopen(bidfile, "r")) is NULL) {
nofile(bidfile); return;
}
while (fgets(port->line, linelen, out) isnt NULL) {
/* the first 4 characters are the date */
strcpy(port->cmd, port->line + 4);
a = port->cmd;
remnl(a);
a = port->line;
b = port->mmhs->bid;
unbl(a, b, ln_bid);
if (match(port->cmd, port->line)) {
needbid = false;
fclose(out);
return;
}
}
needbid = true;
fclose(out);
}
/****************************************
* *
* Code for the commands starts here *
* *
****************************************/
/*
* GM or GR command: backup the mail file.
*/
untmsg()
{
register word inhdr, me;
if (port->opt2 isnt 'A') { if (sure()) return; }
if (!mfhs->count) { port->msg = mm[5]; return; }
prtx(mm[6]);
close(mfl); /* Close current. */
unlink(mbbfile); /* Delete backup */
/*
* Copy current to backup.
*/
if (samedir(mbfile, mbbfile)) rename(mbfile, mbbfile);
else copy(mbfile, mbbfile, false);
unlink(mbfile); /* Delete current. */
/*
* Open new current and backup.
*/
mfl = open(mbfile, O_CREAT | O_RDWR | O_BINARY, pmode);
mflb = open(mbbfile, O_RDONLY | O_BINARY);
read_rec(mflb, 0, (char *)mfhs);
me = mfhs->last;
inhdr = mfhs->first;
inithdr();
if (port->opt2 is 'R')
{
if (port->flds is 1) mfhs->next_msg = 1;
else mfhs->next_msg = atoi(port->fld[1]);
}
while(inhdr <= me) /* For each message header ... */
{
read_rec(mflb, inhdr, (char *)port->mmhs); /* Read the header. */
/*
* Tell the sysop about this message.
*/
sprintf(port->line, "Hdr %6u Size %6u # %6u Read %6u",
inhdr, port->mmhs->size, port->mmhs->number, port->mmhs->read);
outstr(port->line);
inhdr++;
if (!(port->mmhs->stat & ( m_kill | m_busy)))
{
outstr("\n");
/*
* If renumbering messages, renumber this message.
*/
if (port->opt2 is 'R')
{
msgfile(port->line, port->mmhs->number);
msgfile(port->cmd, mfhs->next_msg);
rename(port->line, port->cmd);
port->mmhs->number = mfhs->next_msg++;
}
/*
* Write the header.
*/
port->mmhs->rn = ++mfhs->count;
wt_mmhs();
}
else arcmsg();
}
/*
* Write the file header.
*/
if (mfhs->count) mfhs->first = 1;
mfhs->next = mfhs->count + 1;
mfhs->last = mfhs->count;
mfhs->unt_msg = mfhs->next_msg;
write_rec(mfl, 0, (char *)mfhs);
close(mflb);
clnmsg();
}
/*
* Print headers of unread messages for this user.
*/
newmsg()
{
if (findfwd(port->user->call, ufwd, ufwdn) or
findfwd(port->user->call, bfwd, bfwdn))
{
prtx(mm[2]);
port->opt2 = '\0';
port->flds = 1;
lstmsg();
}
}
/*
* L command, list messages.
*/
lstmsg()
{
register char *p;
register short done, ok;
word h, found, more;
/*
* First set up arguments.
*/
found = 0; more = 0; done = false;
if ((*port->fld[1] is ';') or (*port->fld[2] is ';')) port->flds--;
switch(port->opt2)
{
case '@' :
case '<' :
case '>' : pcall(tcall, port->fld[1]); break;
case '\0': break;
case 'E' :
case ' ' : if (port->flds is 1) more = port->user->msg_number;
default : if (port->flds is 2)
{
if (!num(port->fld[1])) { port->msg = mwhat; return; }
more = atoi(port->fld[1]);
}
}
/*
* Log it, unless is initial login check for msgs.
*/
if (port->opt2)
{
sprintf(port->line, "%u", more);
log('M', 'L', port->opt2, port->line);
}
/*
* Paw through the messages and show what requested.
*/
for (h = mfhs->last; h and !done; h--)
{
read_rec(mfl, h, (char *)port->mmhs);
if ((port->opt2 is 'L') or ((port->opt2 is 'E') and (port->flds is 2)))
done = (found is more); else done = (port->mmhs->number < more);
ok = !done;
/*
* Does this user have read permission for this message?
*/
if (ok) ok = lpermit();
if (ok) if (port->mmhs->stat & m_kill)
ok = ((port->opt2 is 'K') or (port->opt2 is 'E'));
if (ok) if (port->mmhs->stat & m_busy) ok = (port->opt2 is 'E');
/*
* Is this message wanted?
*/
if (ok) switch(port->opt2)
{
case '\0': ok = matchn(port->user->call, port->mmhs->to, ln_call); break;
case 'E' : break;
case 'K' : ok = (port->mmhs->stat & m_kill); break;
case 'F' : ok = (port->mmhs->stat & m_fwd); break;
case 'H' : ok = (port->mmhs->stat & m_hold); break;
case 'L' : break;
case 'M' : ok = matchn(port->user->call, port->mmhs->to, ln_call);
if (!ok) ok = matchn(port->user->call, port->mmhs->from, ln_call);
break;
case 'O' : ok = (port->mmhs->stat & m_stale); break;
case 'U' : ok = !((port->mmhs->type is 'B')or(port->mmhs->type is 'A')
or (port->mmhs->stat & (m_fwd | m_read))); break;
case 'Y' : ok = (port->mmhs->stat & m_read); break;
case '@' : ok = matchn(tcall, port->mmhs->bbs, ln_call); break;
case '<' : ok = matchn(tcall, port->mmhs->from, ln_call); break;
case '>' : ok = matchn(tcall, port->mmhs->to, ln_call); break;
default : ok = ((port->mmhs->type is port->opt2) or
(port->opt2 is ' '));
}
if (ok) prthdr(!found++);
}
if (!found) port->msg = mfind;
s_flag setbit s_update;
}
/*
* CM command: duplicate a message.
*/
dupmsg()
{
word tmpsize;
if (!findmsg(atoi(port->fld[2]))) { port->msg = mnmsg; return; }
port->opt1 = 'S';
prthdr(true);
pcall(port->mmhs->to, port->fld[1]);
fill(port->mmhs->bbs, ' ', ln_call);
port->mmhs->ext = 0;
if (port->flds > 3) atfrom(port->flds - 2);
if (port->flds > 5) atfrom(port->flds - 4);
tmpsize = port->mmhs->size;
msgfile(port->cmd, port->mmhs->number);
initmsg(false);
msgfile(port->line, mfhs->next_msg);
copy(port->cmd, port->line, false);
filesize = tmpsize;
cremsg();
}
/*
* F command: copy a message to a file.
*/
filmsg()
{
register char *p;
register short hdr, append;
register FILE *out;
if (!findmsg(atoi(port->fld[1]))) { port->msg = mnmsg; return; }
hdr = true;
append = false;
if (port->flds is 4) for (p = port->fld[3]; *p; p++) switch (*p)
{
case 'A' : append = true; break;
case 'N' : hdr = false; break;
default: ;
}
if (port->opt2 is ' ') strcpy(port->line, port->fld[2]);
else if (getdir(port->fld[2]) is NULL) { port->msg = mndir; return; }
if (append) out = fopen (port->line, "a"); else
{
if ((out = fopen (port->line, "r")) isnt NULL)
{ fclose(out); port->msg = mexst; return; }
out = fopen (port->line, "w");
}
if (out is NULL) { port->msg = mcant; return; }
sprintf(tmp->scr, "%s %s", port->fld[1], port->line);
log('M', 'D', port->opt2, tmp->scr);
prthdr(true);
if (hdr) fputs(tmp->scr, out);
msgfile(port->cmd, port->mmhs->number);
if ((port->fl = fopen(port->cmd, "r")) is NULL)
{ fclose(out); nofile(port->cmd); return; }
fseek( port->fl, (long)RECSIZE, 0);
while (fgets(tmp->scr, scrmax, port->fl) isnt NULL) fputs(tmp->scr, out);
fclose(port->fl);
fclose(out);
}
/*
* Upload the message text file.
*/
uloadm(tname)
char *tname;
{
register char *tp;
register PORTS *p;
short first;
p = port;
if ((p->fl = fopen(tname, "w")) is NULL) { p->msg = mcant; return false; }
fseek( p->fl, (long)RECSIZE, 0);
first = true;
filesize = 0;
while (true)
{
while(!getdat());
/*
* If user disconnected, timed out, or forced off, zap the file.
*/
if (p->mode & gone)
{
fclose(p->fl);
return false;
}
/*
* If the first line is not a header (thus it is a human entering
* the message), make sure there is an initial blank line before
* the body of the message.
*/
if (first)
{
first = false;
if (!ishead(p->line)) if (*p->line isnt '\n') fputs("\n", p->fl);
}
/*
* Stuff the line into the file.
*/
if (match(p->line, "/EX\n") or match(p->line,"/ex\n"))
{
fclose(p->fl);
return true;
}
if ((tp = strchr(p->line, cpmeof)) is NULL)
{
filesize += strlen(p->line);
fputs(p->line, p->fl);
}
else
{
if (tp isnt p->line)
{
*tp++ = '\n';
*tp = '\0';
filesize += strlen(p->line);
fputs(p->line, p->fl);
}
fclose(p->fl);
return true;
}
}
}
/*
* "Display the message text" utility.
*/
dloadm(sh)
short sh;
{
short first;
sprintf(port->line, "%u", port->mmhs->number);
log('M', 'R', port->opt2, port->line);
port->mmhs->read++;
if (matchn(port->user->call, port->mmhs->to, ln_call))
port->mmhs->stat setbit m_read;
wt_mmhs();
makehdr2();
prthdr(true);
msgfile(port->line, port->mmhs->number);
if ((port->fl = fopen(port->line, "r")) is NULL)
{ nofile(port->line); return; }
fseek( port->fl, (long)RECSIZE, 0 );
pgst(NULL);
pgck(); /* First line of header */
pgck(); /* Second line of header */
pgck(); /* Path line */
if (port->mmhs->ext) pgck();
if (*port->mmhs->bid isnt ' ') pgck();
strcpy(tmp->scr, " Path: ");
first = true;
while(fgets(port->line, linelen, port->fl) isnt NULL)
{
if (!sh)
{
sh = !parsehd(port->line);
if (sh)
{
if (!first)
{
strcat(tmp->scr, "\n\n");
outstr(tmp->scr);
pgck();
prtx("Date: $j/$k\n"); pgck();
prtx("From: $P @ $a\n"); pgck();
prtx("Message-Id: <$m@$a>\n"); pgck();
prtx("To: $G @ ");
if (*port->mmhs->bbs is ' ') prtx("$O\n");
else if (port->mmhs->ext is 2) prtx("$h\n");
else prtx("$A\n"); pgck();
prtx("Subject: $E\n\n"); pgck();
}
}
else
{
if (!first) strcat(tmp->scr, "!");
strcat(tmp->scr, orgbbs);
first = false;
}
}
if (sh)
{
outstr(port->line);
if ((pgck() is 'Q') or (chkdis())) { fclose(port->fl); return; }
}
}
fclose (port->fl);
}
/*
* RM command: read my messages.
*/
rdmsgm()
{
register short found;
register word h;
found = false;
for (h = mfhs->first; h and h <= mfhs->last; h++)
{
read_rec(mfl, h, (char *)port->mmhs);
if (!(port->mmhs->stat & (m_read | m_fwd | m_hold | m_busy)) and
matchn(port->user->call, port->mmhs->to, ln_call))
{
dloadm(false);
found = true;
if (pause() is 'Q') return;
}
}
if (!found) port->msg = mfind;
}
/*
* R command: read one message.
*/
rdmsg()
{
if (!num(port->fld[1])) { port->msg = mwhat; return; }
if (!findmsg(atoi(port->fld[1]))) { port->msg = mnmsg; return; }
if (!rpermit()) { port->msg = mprot; return; }
dloadm(port->opt2 is 'H');
}
/*
* KF, KM, KO, KY, KK commands, kill multiple messages.
*/
klmsgm()
{
register short ok;
register short found;
word h, next;
if (port->flds is 2) pcall(tcall, port->fld[1]);
found = false;
for (h = mfhs->first; h and h <= mfhs->last; h++)
{
read_rec(mfl, h, (char *)port->mmhs);
ok = kpermit();
if (ok) ok = !(port->mmhs->stat & m_hold);
if (ok) if (port->flds is 2) ok = matchn(tcall, port->mmhs->to, ln_call);
if (ok) switch(port->opt2)
{
case 'F' : ok = (port->mmhs->stat & m_fwd); break;
case 'M' :
ok = ((port->mmhs->stat & m_read) and
matchn(port->user->call, port->mmhs->to, ln_call));
break;
case 'O' : ok = (port->mmhs->stat & m_stale); break;
case 'Y' : ok = (port->mmhs->stat & m_read); break;
}
if (ok)
{
sprintf(port->line, "%u", port->mmhs->number);
log('M', 'K', port->opt2, port->line);
prtx(mm[7]);
found = true;
port->mmhs->stat setbit m_kill;
write_rec(mfl, port->mmhs->rn, (char *)port->mmhs);
makehdr2();
}
}
if (!found) port->msg = mfind;
}
/*
* K command, kill a message.
*/
klmsg()
{
register short dosvc;
if (!num(port->fld[1])) { port->msg = mwhat; return; }
if (!findmsg(atoi(port->fld[1]))) { port->msg = mnmsg; return; }
if (port->mmhs->stat & m_kill) { port->msg = mnmsg; return; }
if (!kpermit()) { port->msg = mprot; return; }
log('M', 'K', port->opt2, port->fld[1]);
dosvc = (port->opt2 is 'T') and
(port->mmhs->type is 'T') and
(s_param & s_svc);
if (dosvc) findat();
/*
* Marked the message as Killed.
*/
port->mmhs->stat setbit m_kill;
write_rec(mfl, port->mmhs->rn, (char *)port->mmhs);
makehdr2();
/*
* If this is KT of T type message, and we do service messages,
* do the service message.
*/
if (dosvc)
{
port->opt1 = 'S';
strncpy(port->mmhs->to, port->mmhs->from, ln_call);
strncpy(port->mmhs->from, cport->user->call, ln_call);
port->mmhs->type = 'S';
fill(port->mmhs->bid, ' ', ln_bid);
port->mmhs->ext = 0;
initmsg(false);
msgfile(port->line, mfhs->next_msg);
port->fl = fopen(port->line, "w");
fseek(port->fl, (long)RECSIZE, 0);
fprintf(port->fl, "Msg %5u taken from %6.6s by %6.6s at %4.4s on %6.6s\n",
port->mmhs->number, cport->user->call, port->user->call, l_time, l_date);
fclose(port->fl);
filesize = 56;
cremsg();
}
port->msg = mdone;
}
/*
* S command: send a message.
*/
sndmsg()
{
FILE *out;
char *a, *b;
holdit = false; /* initialize it to something */
pfld();
if (port->mode & gone) return;
if (bidok) {
if (!needbid) return;
}
else {
if (port->user->options & (u_bbs | u_expert)) outstr("Msg:\n");
else prtx(mm[1]);
}
msgfile(port->cmd, mfhs->next_msg);
if (!uloadm(port->cmd)) return;
/*
* If this is a Bulletin and has no BID,
* parse the headers and give it one.
*/
if (!hasbid)
if (!iscall(port->mmhs->to))
if (port->mmhs->type is 'B')
{
msgfile(port->cmd, mfhs->next_msg);
a = port->line;
b = cport->user->call;
unbl(a, b, 6);
/* Default the BID as to coming from this BBS with our msg number. */
sprintf(tmp->scr, "%-u_%-s", mfhs->next_msg, port->line);
/* Now parse the headers if it came from another BBS. */
if ((out = fopen(port->cmd, "r")) is NULL)
{
nofile(port->cmd); return;
}
fseek(out, (long)RECSIZE, 0);
while (fgets(port->line, linelen, out) isnt NULL)
{
if (parsehd(port->line))
{
sprintf(tmp->scr, "%s_%s", orgmsg, orgbbs);
}
}
fclose(out);
strncpy(port->mmhs->bid, tmp->scr, ln_bid);
hasbid = true;
}
checkbid();
if (!needbid) holdit = true;
else holdit = false;
/* If a message is to an individual,
* automatically make it a private message.
*/
if (port->opt2 is ' ')
if (iscall(port->mmhs->to)) port->mmhs->type = 'P';
cremsg();
}
/*
* SM command, send a message to a distribution list.
*/
sndmlt()
{
register FILE *fl;
char fn[80];
register short first = true;
word tmpsize;
holdit = false;
fill(port->mmhs->bid, ' ', ln_bid);
if ((fl = fopen(port->fld[1], "r")) is NULL)
{ nofile(port->fld[1]); return; }
prtx(mm[0]);
get_title();
if (port->mode & gone) { fclose(fl); return; }
if (port->flds is 3) if (*port->fld[port->flds-1] is '$')
{
if (*(port->fld[port->flds-1] + 1) isnt NULL)
{
strncpy(port->mmhs->bid, port->fld[port->flds-1] + 1, ln_bid);
hasbid = true;
}
}
prtx(mm[1]);
strncpy(port->mmhs->from, port->user->call, ln_call);
port->mmhs->ext = 0;
initmsg(false);
msgfile(fn, mfhs->next_msg);
if (!uloadm(fn)) { fclose(fl); return; }
tmpsize = filesize;
while (fgets(port->line, linelen, fl) isnt NULL)
{
parse();
if (!first)
{
port->mmhs->ext = 0;
initmsg(false);
msgfile(port->line, mfhs->next_msg);
copy(fn, port->line, false);
}
port->mmhs->type = port->opt2;
pcall(port->mmhs->to, port->fld[1]);
fill(port->mmhs->bbs, ' ', ln_call);
if(port->flds > 3) atfrom(2);
if(port->flds > 5) atfrom(4);
filesize = tmpsize;
cremsg();
first = false;
}
fclose(fl);
}
/*
* M command, make a message from a file.
*/
makmsg()
{
if ((port->fl = fopen(port->fld[2], "r")) is NULL)
{ nofile(port->fld[2]); return; }
fclose(port->fl);
pfld();
if (port->mode & gone) return;
msgfile(port->line, mfhs->next_msg);
copy(port->fld[2], port->line, true);
cremsg();
}
/*
* MM command, make multiple messages from a file.
*/
makmlt()
{
register FILE *dfl;
char tnm[80];
holdit = false;
fill(port->mmhs->bid, ' ', ln_bid);
if ((port->fl = fopen(port->fld[2], "r")) is NULL)
{ nofile(port->fld[2]); return; }
fclose(port->fl);
if ((dfl = fopen(port->fld[1], "r")) is NULL)
{ nofile(port->fld[1]); return; }
strcpy(tnm, port->fld[2]);
if (port->flds is 4) if (*port->fld[port->flds-1] is '$')
{
if (*(port->fld[port->flds - 1] + 1) isnt NULL)
{
strncpy(port->mmhs->bid, port->fld[port->flds-1] + 1, ln_bid);
hasbid = true;
}
}
prtx(mm[0]);
get_title();
if (port->mode & gone) { fclose(dfl); return; }
while (fgets(port->line, linelen, dfl) isnt NULL)
{
parse();
port->mmhs->type = port->opt2;
pcall(port->mmhs->to, port->fld[1]);
strncpy(port->mmhs->from, port->user->call, ln_call);
fill(port->mmhs->bbs, ' ', ln_call);
port->mmhs->ext = 0;
if (port->flds > 3) atfrom(2);
if (port->flds > 5) atfrom(4);
initmsg(false);
msgfile(port->line, mfhs->next_msg);
copy(tnm, port->line, true);
cremsg();
}
fclose(dfl);
}
/*
* Mark stale messages.
*/
stale()
{
register word i;
register int ts;
for (i = mfhs->first; i and i <= mfhs->last; i++)
{
read_rec(mfl, i, (char *)port->mmhs);
ts = tstaleb;
if (port->mmhs->type is 'T') ts = tstalen;
else if (iscall(port->mmhs->to)) ts = tstaleu;
if (!(port->mmhs->stat & m_stale))
if (ddiff(port->mmhs->date, l_date) > ts)
{
port->mmhs->stat setbit m_stale;
write_rec(mfl, i, (char *)port->mmhs);
}
}
}
/*
* DW command: make wp message from user file.
*/
dwuser()
{
register int i;
register short first = true;
short doall;
if (*wpcall is ' ') return;
doall = port->flds is 2;
port->opt1 = 'S';
filesize = 0;
for (i = 1; i <= ufhs->count; i++)
{
read_rec(ufl, i, (char *)tuser);
if ((tuser->state & u_home) and (tuser->state & u_zip))
if (doall or !(tuser->state & u_sent))
{
if (first)
{
first = false;
port->mmhs->type = 'P';
strncpy(port->mmhs->to, "WP ", ln_call);
strncpy(port->mmhs->from, cport->user->call, ln_call);
strncpy(port->mmhs->bbs, wpcall, ln_call);
strcpy(port->mmhs->title, "WP Update");
fill(port->mmhs->bid, ' ', ln_bid);
port->mmhs->ext = 0;
initmsg(false);
msgfile(port->line, mfhs->next_msg);
port->fl = fopen(port->line, "w");
}
filesize += 29;
fseek(port->fl, (long)RECSIZE, 0);
fprintf(port->fl, "%6.6s qth %6.6s zip %6.6s\n",
tuser->call, tuser->home_bbs, tuser->zip);
tuser->state setbit u_sent;
write_rec(ufl, i, (char *)tuser);
if (i is port->user->rn) port->user->state setbit u_sent;
}
}
if (!first)
{
fclose(port->fl);
cremsg();
}
}
/*
* E command, edit a message header.
*/
edmsg()
{
FILE *out;
char *a, *b;
if (!findmsg(atoi(port->fld[1]))) { port->msg = mnmsg; return; }
while (*port->fld[0] isnt '\0')
{
prthdr();
outstr("t(Y)pe, (S)tatus, (T)o, (F)rom, (B)bs, t(I)tle, bi(D)\n");
getcmd();
if (port->mode & gone) return;
switch (*port->fld[0])
{
case 'T' : pcall(port->mmhs->to, port->fld[1]); break;
case 'F' : pcall(port->mmhs->from, port->fld[1]); break;
case 'B' : edbbs(1); break;
case 'I' : if (*port->fld[1])
{
remnl(port->line);
strncpy(port->mmhs->title, port->line+2, mhtitl);
}
else *port->mmhs->title = '\0';
break;
case 'S' : switch(*port->fld[1])
{
case 'F' : port->mmhs->stat = m_fwd; break;
case 'H' : port->mmhs->stat = m_hold; break;
case 'N' : port->mmhs->stat = 0; break;
case 'O' : port->mmhs->stat = m_stale; break;
case 'Y' : port->mmhs->stat = m_read; break;
}
break;
case 'Y' : if(*port->fld[1]) port->mmhs->type = *port->fld[1];
else port->mmhs->type = ' '; break;
case 'D' : if(*port->fld[1]) strncpy(port->mmhs->bid, port->fld[1], ln_bid);
else fill(port->mmhs->bid, ' ', ln_bid);
break;
}
}
wt_mmhs();
makehdr2();
if (*port->mmhs->bid isnt ' ')
{
checkbid();
if (needbid)
{
if ((out = fopen(bidfile,"a")) is NULL)
{
port->msg = mcant; return;
}
a = port->cmd;
b = port->mmhs->bid;
unbl(a, b, ln_bid);
sprintf(port->line, "%4.4s%s\n", port->mmhs->date + 2, port->cmd);
if (s_flag & s_dv) begin_lock();
fputs(port->line, out);
if (s_flag & s_dv) end_lock();
fclose(out);
}
}
}
/*
* ET command, edit an NTS traffic message header.
*/
edtfc()
{
register short ok;
if (!findmsg(atoi(port->fld[1]))) { port->msg = mnmsg; return; }
prthdr();
ok = (port->mmhs->type is 'T');
if (!ok) ok = ((port->mmhs->type is ' ') and matchn(port->mmhs->to, "NTS", 3));
if (!ok) { port->msg = mm[12]; return; }
prtx(mm[8]);
getcmd();
if (port->mode & gone) return;
if (port->flds) pcall(port->mmhs->to, port->fld[0]);
prtx(mm[9]);
getcmd();
if (port->mode & gone) return;
edbbs(0);
prtx(mm[10]);
getcmd();
if (port->mode & gone) return;
if (port->flds)
{
remnl(port->line);
strncpy(port->mmhs->title, port->line, mhtitl);
}
else if (*port->line is ' ') *port->mmhs->title = '\0';
prtx(mm[11]);
getcmd();
if (port->mode & gone) return;
if (port->flds) port->mmhs->type = *port->fld[0];
else if (*port->line is ' ') port->mmhs->type = ' ';
port->mmhs->stat = 0;
prthdr();
wt_mmhs();
makehdr2();
sprintf(port->line, "%u %-.6s %s",
port->mmhs->number, port->mmhs->to, port->mmhs->title);
log('M', 'E', port->opt2, port->line);
}
edbbs(f)
int f;
{
fill(port->mmhs->call, '\0', 125);
port->mmhs->ext = 0;
fill(port->mmhs->bbs, ' ', ln_call);
if(*port->fld[f])
{
pcall(port->mmhs->bbs, port->fld[f]);
if (strchr(port->fld[f], '.') is NULL) dodis();
else
{
port->mmhs->ext = 2;
strncpy(port->mmhs->call[0], port->fld[f], 64);
}
}
}